package reflect.annotation;

import annotation.AutoRunClass;
import annotation.AutoRunMethod;
import reflect.ReflectDemo;

import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URISyntaxException;
import java.util.Objects;

/**
 * 反射注解demo
 *
 * 有关注解的更多demo在annotation包中
 * */
public class ReflectAnnotationDemo {
    public static void main(String[] args) throws ClassNotFoundException, URISyntaxException,
            InstantiationException, IllegalAccessException, InvocationTargetException {
        Demo1();
        System.out.println("===========================================");
        Demo2();
        System.out.println("===========================================");
        demo3();
        System.out.println("===========================================");
        demo4();
    }

    private static void Demo1() throws ClassNotFoundException {
        Class<?> c = Class.forName("reflect.Person");
        if (c.isAnnotationPresent(AutoRunClass.class))
            System.out.println("该类被注解AutoRunClass标注了");
    }

    /**
     * 扫描ReflectDemo类所在的包下的所有类并实例化，查看哪些被@AutoRunClass注解标注
     * */
    private static void Demo2() throws ClassNotFoundException, URISyntaxException,
            InstantiationException, IllegalAccessException {
        File file = new File(Objects.requireNonNull(ReflectDemo.class.getResource(".")).toURI());
        System.out.println(file.getPath());
        String packageName = file.getName();
        File[] classFiles = file.listFiles(f -> f.getName().endsWith(".class"));
        for (File temp: classFiles) {
            String className = packageName + "." + temp.getName().split("\\.")[0];
            Class<?> c = Class.forName(className);
            if (c.isAnnotationPresent(AutoRunClass.class)) {
                System.out.println(className + "类被注解AutoRunClass标注了");
                System.out.println("实例化" + className);
                Object o = c.newInstance();
                System.out.println(o);
            }
            else
                System.out.println(className + "类没有被注解AutoRunClass标注了");
        }
    }

    /**
     * 扫描ReflectDemo类所在的包下被@AutoRunClass注解标注的所有类并实例化，
     * 以及调用类中被@AutoRunMethod注解标注的方法
     * */
    private static void demo3() throws ClassNotFoundException, InstantiationException,
            IllegalAccessException, URISyntaxException, InvocationTargetException {
        File file = new File(Objects.requireNonNull(ReflectDemo.class.getResource(".")).toURI());
        String packageName = file.getName();
        File[] classFiles = file.listFiles(f -> f.getName().endsWith(".class"));
        for (File temp: classFiles) {
            String className = packageName + "." + temp.getName().split("\\.")[0];
            Class<?> c = Class.forName(className);
            if (c.isAnnotationPresent(AutoRunClass.class)) {
                System.out.println(className + "类被注解AutoRunClass标注了");
                System.out.println("实例化" + className);
                Object o = c.newInstance();
                Method[] methods = c.getDeclaredMethods();
                for (Method method : methods) {
                    if (method.isAnnotationPresent(AutoRunMethod.class)) {
                        System.out.println("-----------------------");
                        System.out.println("自动调用方法：" + method.getName());
                        method.invoke(o);
                        System.out.println("-----------------------");
                    }
                }
            }
        }
    }

    /**
     * 扫描ReflectDemo类所在的包下被@AutoRunClass注解标注的所有类并实例化，
     * 以及调用类中被@AutoRunMethod注解标注的方法
     * 并获取注解中的值，根据该值指定调用方法的执行的次数
     * */
    private static void demo4() throws ClassNotFoundException, InstantiationException,
            IllegalAccessException, URISyntaxException, InvocationTargetException {
        File file = new File(Objects.requireNonNull(ReflectDemo.class.getResource(".")).toURI());
        String packageName = file.getName();
        File[] classFiles = file.listFiles(f -> f.getName().endsWith(".class"));
        for (File temp: classFiles) {
            String className = packageName + "." + temp.getName().split("\\.")[0];
            Class<?> c = Class.forName(className);
            if (c.isAnnotationPresent(AutoRunClass.class)) {
                System.out.println(className + "类被注解AutoRunClass标注了");
                System.out.println("实例化" + className);
                Object o = c.newInstance();
                Method[] methods = c.getDeclaredMethods();
                for (Method method : methods) {
                    if (method.isAnnotationPresent(AutoRunMethod.class)) {
                        // 返回当前method对象表示的方法付上的注解@AutoRunMethod
                        AutoRunMethod arm = method.getAnnotation(AutoRunMethod.class);
                        int value = arm.value();
                        System.out.println("-----------------------");
                        for (int i = 0; i < value; i++) {
                            System.out.println("自动调用方法：" + method.getName());
                            method.invoke(o);
                        }
                        System.out.println("-----------------------");
                    }
                }
            }
        }
    }
}
